﻿#include "clienthandle.h"
#include <QEventLoop>   // 事件循环类
#include <QJsonDocument> // json文档对象
#include <QJsonObject> // json对象
#include <QJsonArray> // json数组
#include <QJsonParseError> // json错误信息
#include "clientrequest.h"
#include "onlineusers.h"

ClientHandle::ClientHandle(QObject *parent) : QObject(parent)
{
    setAutoDelete(true);
}

// 设置套接字
void ClientHandle::SetSocket(qintptr sock)
{
    this->sock = sock;
}

// 重写run函数
void ClientHandle::run()
{
    sockPtr = std::make_shared<QTcpSocket>(); // 创建一个新的QTcpSocket对象
    sockPtr->setSocketDescriptor(sock); // 将创建的QTcpSocket对象绑定到传入的socket描述符上

    QEventLoop loop;

    // TCP有数据可读
    connect(sockPtr.get(), &QTcpSocket::readyRead, [this]()
    {
        // 读取来自tcp缓冲区的所有数据
        buffer += sockPtr->readAll();
        while (buffer.size() >= sizeof(int)) // 如果读取的数据大小大于包头，说明有需要读取的数据
        {
            int size = 0;
            memcpy(&size, buffer, sizeof(int)); // 真实数据大小
            if (buffer.size() < size + sizeof(int)) // 如果读取的数据大小小于真实数据大小和包头大小之和，说明真实数据没有传完
            {
                return; // 返回继续读取到buffer
            }
            QByteArray data = buffer.mid(sizeof(int), size); // 截取一次的json数据
            buffer.remove(0, size + sizeof(int)); // 把已读取的数据删去

            process(data); // 处理json逻辑
        }
    });

    // 客户端断开连接
    connect(sockPtr.get(), &QTcpSocket::disconnected, [this]()
    {
        OnlineUsers::getInstance()->RemoveUsers(this);
    });

    // 客户端断开连接，退出事件循环
    connect(sockPtr.get(), &QTcpSocket::disconnected, &loop, &QEventLoop::quit);

    loop.exec();//开启事件循环，阻塞线程
}

// 处理json逻辑
void ClientHandle::process(const QByteArray &data)
{
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error); // 将输入的二进制数据(data)解析为JSON文档
    if (doc.isNull()) // JSON解析失败处理
    {
        QJsonObject obj;
        obj["result"] = 0; // 设置结果状态码为0，表示接收失败
        obj["msg"] = error.errorString(); // 将解析错误信息存储到"msg"字段
        WriteToClient(QJsonDocument(obj).toJson()); // 将错误响应写回客户端
    }
    qDebug() << "clienthandle.cpp处理json逻辑:" << doc.toJson() << endl;

    QString request = doc.object()["request"].toString(); // 提取请求字段

    // 工厂模式
    Factory::getInstance()->getProcess(request)->ProcessRequest(this, doc.object()); // 根据接收到的请求执行对应的函数
}

// 回传给客户端
void ClientHandle::WriteToClient(const QByteArray &data)
{
    int size = data.size();
    // 先写包头
    sockPtr->write((char *)&size, sizeof(int));
    sockPtr->write(data);
}
